package com.hqd.ch03.v34.web.servlet.mvc.method;

import com.hqd.ch03.v34.web.bind.annotation.RequestMethod;
import com.hqd.ch03.v34.web.servlet.mvc.condition.PatternsRequestCondition;
import com.hqd.ch03.v34.web.servlet.mvc.condition.RequestCondition;
import com.hqd.ch03.v34.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.apache.commons.lang3.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Set;

public class RequestMappingInfo implements RequestCondition<RequestMappingInfo> {
    private static final PatternsRequestCondition EMPTY_PATTERNS = new PatternsRequestCondition();

    private static final RequestMethodsRequestCondition EMPTY_REQUEST_METHODS = new RequestMethodsRequestCondition();

    /**
     * 路径匹配
     */
    private final PatternsRequestCondition patternsCondition;
    /**
     * 请求方法匹配
     */
    private final RequestMethodsRequestCondition methodsCondition;

    private RequestMappingInfo(PatternsRequestCondition patternsCondition,
                               RequestMethodsRequestCondition methodsCondition) {
        this.patternsCondition = patternsCondition;
        this.methodsCondition = methodsCondition;
    }

    public static Builder paths(String... paths) {
        return new DefaultBuilder(paths);
    }

    @Override
    public RequestMappingInfo combine(RequestMappingInfo other) {
        PatternsRequestCondition patterns =
                (this.patternsCondition != null && other.patternsCondition != null ?
                        this.patternsCondition.combine(other.patternsCondition) : null);
        RequestMethodsRequestCondition methods = this.methodsCondition.combine(other.methodsCondition);
        return new RequestMappingInfo(patterns, methods);
    }

    @Override
    public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
        RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
        if (methods == null) {
            return null;
        }
        PatternsRequestCondition patterns = null;
        if (this.patternsCondition != null) {
            patterns = this.patternsCondition.getMatchingCondition(request);
            if (patterns == null) {
                return null;
            }
        }
        return new RequestMappingInfo(patterns, methods);
    }

    public Set<String> getDirectPaths() {
        return this.patternsCondition.getDirectPaths();
    }

    @Override
    public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
        return 0;
    }

    public interface Builder {
        Builder paths(String... paths);

        Builder methods(RequestMethod... methods);

        RequestMappingInfo build();
    }

    private static class DefaultBuilder implements Builder {

        private String[] paths;

        private RequestMethod[] methods = new RequestMethod[0];


        public DefaultBuilder(String... paths) {
            this.paths = paths;
        }

        @Override
        public Builder paths(String... paths) {
            this.paths = paths;
            return this;
        }

        @Override
        public DefaultBuilder methods(RequestMethod... methods) {
            this.methods = methods;
            return this;
        }


        @Override
        public RequestMappingInfo build() {
            PatternsRequestCondition patterns = ObjectUtils.isEmpty(this.paths) ?
                    EMPTY_PATTERNS : new PatternsRequestCondition(this.paths);
            return new RequestMappingInfo(patterns,
                    com.hqd.ch03.utils.ObjectUtils.isEmpty(this.methods) ?
                            EMPTY_REQUEST_METHODS : new RequestMethodsRequestCondition(this.methods));
        }
    }
}
